package com.org.oracle.consumer;

import com.org.oracle.constant.MQConstants;
import com.org.oracle.constant.RedisKeyConstants;
import com.org.oracle.mapper.UserCountMapper;
import com.org.oracle.mongodb.dto.NoteOperateMqDTO;
import com.org.oracle.util.JsonUtils;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.rocketmq.common.message.Message;
import org.apache.rocketmq.spring.annotation.RocketMQMessageListener;
import org.apache.rocketmq.spring.core.RocketMQListener;
import org.checkerframework.checker.guieffect.qual.UI;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.Objects;

/**
 * @author: heiye
 * @date: 2024/12/16 下午12:49
 * @version: v1.0.0
 * @description: 计数: 笔记发布数
 */
@Slf4j
@Component
@RocketMQMessageListener(
        // Group 组
        consumerGroup = "oracle_group_" + MQConstants.TOPIC_NOTE_OPERATE,
        // 消费的主题 Topic
        topic = MQConstants.TOPIC_NOTE_OPERATE
)
public class CountNotePublishConsumer implements RocketMQListener<Message> {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private UserCountMapper userCountMapper;

    @Override
    public void onMessage(Message message) {
        // 消息体
        String bodyJsonStr = new String(message.getBody());
        // 标签
        String tags = message.getTags();

        log.info("==> CountNotePublishConsumer 消费了消息 {}, tags: {}", bodyJsonStr, tags);

        // 根据 MQ 标签，判断笔记操作类型
        // 笔记发布
        if (Objects.equals(tags, MQConstants.TAG_NOTE_PUBLISH)) {
            handleTagMessage(bodyJsonStr, 1);
        }
        // 笔记删除
        else if (Objects.equals(tags, MQConstants.TAG_NOTE_DELETE)) {
            handleTagMessage(bodyJsonStr, -1);
        }
    }

    /**
     * 笔记发布、删除
     * @param bodyJsonStr
     */
    private void handleTagMessage(String bodyJsonStr, long count) {
        // 消息体 JSON 字符串转 DTO
        NoteOperateMqDTO noteOperateMqDTO = JsonUtils.parseObject(bodyJsonStr, NoteOperateMqDTO.class);

        if (Objects.isNull(noteOperateMqDTO)) {
            return;
        }

        // 笔记发布者 ID
        String creatorId = noteOperateMqDTO.getCreatorId();

        // 更新 Redis 中用户维度的计数 Hash
        String countUserKey = RedisKeyConstants.buildCountUserKey(creatorId);
        // 判断 Redis 中 Hash 是否存在
        Boolean hasKey = redisTemplate.hasKey(countUserKey);

        // 若存在才会更新
        // (因为缓存设有过期时间，考虑到过期后，缓存会被删除，这里需要判断一下，存在才会去更新，而初始化工作放在查询计数来做)
        if (hasKey) {
            // 对目标用户 Hash 中的笔记发布总数，进行加减操作
            redisTemplate.opsForHash().increment(countUserKey, RedisKeyConstants.FIELD_NOTE_TOTAL, count);
        }

        // 更新 user_count 表
        userCountMapper.insertOrUpdateNoteTotalByUserId(count, creatorId);
    }
}
